#ifndef INSTRUCTIONSIMPLE_H
#define INSTRUCTIONSIMPLE_H

/*!
 * \file instructionsimple.h
 * \brief Classe qui représente une instruction au sens LOBO, cette classe permet de vérifier et traduire une instruction LOBO en chaine-instruction C++ équivalente
 * \author bruneau-hay
 * \version 0.1
 */

#include "fonction.h"
#include "trim.h"
#include <time.h>
#include <stdlib.h>
#include <regex.h>
#include <algorithm>

using namespace std;

class instructionsimple
{
private:
  string type; /*Type de l'instructionsimple parmi AFFECTE AFFICHE APPEL ...*/
  string inst; /*Contenu de l'instruction */
  fonction * fun; /*Pointeur sur la fonction à laquelle l'instructionsimple appartient*/
  vector<string> elements; /*Contient les éléments de inst */
  stringstream flux_erreur; /*Le flux où sont écrites les erreur */
  
  bool valide; /*Valeur de validité de l'instructionsimple */
  
public:
/*!
 * \brief Constructeur d'instructionsimple
 * 
 * Constructeur d'instructionsimple avec un type, le reste, et une valeur de validité 
 * (si on est sûr de la validité on peut shunter la validation ->unused)
 * \param typ : le type de l'instruction
 * \param instr : contenu de l'instruction
 * \param valid : valeur de validité 
 */
instructionsimple(string typ,string instr, fonction * f, bool valid); //verifie au passage la validité de l'instruction

/*!
 * \brief Traduction vers une instruction-chaine c++
 */
string translate();

/*!
 * \brief Affichage de l'instructionsimple
 */
void printInst();

/*!
 * \brief Vérification d'une instructionsimple de type DECLARE
 * 
 * Vérification d'une instructionsimple de type DECLARE
 * Si l'instructionsimple est valide on ajoute la variable déclarée aux variables de fun
 * Si non valide on écrit dans flux_erreur
 */
void VDeclare();

/*!
 * \brief Vérification d'une instructionsimple de type AFFECTE
 * 
 * Vérification d'une instructionsimple de type AFFECTE
 * Si l'instructionsimple est valide on "initialise" la variable concernée dans les variables de fun
 * Si non valide on écrit dans flux_erreur
 */
void VAffecte();

/*!
 * \brief Vérification d'une instructionsimple de type AFFICHE
 * 
 * Vérification d'une instructionsimple de type AFFICHE
 * Si non valide on écrit dans flux_erreur
 */
void VAffiche();

/*!
 * \brief Vérification d'une instructionsimple de type APPEL
 * 
 * Vérification d'une instructionsimple de type APPEL
 * On vérifie l'éxistence de la fonction appellée et les paramètres
 * Si non valide on écrit dans flux_erreur
 */
void VAppel();

/*!
 * \brief Vérification d'une instructionsimple de type RETOUR
 * 
 * Vérification d'une instructionsimple de type RETOUR
 * Si non valide on écrit dans flux_erreur
 */
void VRetour();

/*!
 * \brief Vérification d'une instructionsimple de type REPETE
 * 
 * Vérification d'une instructionsimple de type REPETE
 * Si non valide on écrit dans flux_erreur
 */
void VRepete();

/*!
 * \brief Validité d'un identifiant
 * 
 * \param id: la chaine à tester
 * \return true si id est de la forme [a-zA-Z][[a-zA-Z]*[0-9]]*
 */
bool isID(const string& id);

/*!
 * \brief Validité d'un opérateur binaire
 * 
 * \param op: la chaine à tester
 * \return true si op est l'un des opérateurs binaires autorisés
 */
bool isOpBin(const string& op);

/*!
 * \brief Validité d'un nombre
 * 
 * \param arg1: la chaine à tester
 * \return true si arg1 est un nombre
 */
bool isNumber(const string& arg1);

/*!
 * \brief Validité d'une notation polonaise inversée
 * 
 * \param arg: la chaine à tester
 * \return true si arg est une notation polonaise inversée
 */
bool isExpression(const string & arg);

/*!
 * \brief Validité d'une chaine
 * 
 * \param arg: la chaine à tester
 * \return true si arg est correctement formé
 */
bool isChaine(const string & arg);

/*!
 * \brief Validité de l'instructionsimple
 *
 * \return la valeur de valide
 */
bool isValid();

/*!
 * \brief Parsage de la chaine
 * 
 * \param str: la chaine à parser
 * \param tokens : le conteneur des chaines trouvées
 * \param delimiters : le séparateur
 */
void tokenize(const string& str, vector<string>& tokens, const string& delimiters = " " );

/*!
 * \brief Traduction d'une expression polonaise inversée
 * 
 * \return la traduction
 */
string translateExpression(const string & arg);
};

#endif 
